//
//  TTNetHelper.m
//  01-AFN
//
//  Created by peironggao on 2017/10/14.
//  Copyright © 2017年 gaopeirong. All rights reserved.
//

#import "TTNetHelper.h"
#import "TTURLSessionManager.h"
#include <sys/time.h>

NSString *TTNetHelperResponseDomain         = @"TTNetHelperResponseDomain";
NSString *TTNetHelperResponseUserDomainKey  = @"TTNetHelperResponseUserDomainKey";

#define TTSERVER_BASE_URL_STRING            @"http://baidu.com"


@interface TTNetHelper ()

@property (nonatomic, strong) NSMutableDictionary<NSString *, NSURLSessionDataTask *> *requestTask;

@property (nonatomic, strong) dispatch_queue_t requestTaskCacheQueue;

@end

@implementation TTNetHelper

- (instancetype)init
{
    if (self = [super init])
    {
        _requestTask = [NSMutableDictionary dictionary];
        _requestTaskCacheQueue = dispatch_queue_create("tt_task_queue", DISPATCH_QUEUE_SERIAL);
        dispatch_queue_set_specific(_requestTaskCacheQueue, &_requestTask, (__bridge void * _Nullable)(self), NULL);
    }
    return self;
}

- (void)dealloc
{
    [self runSyc:^{
        [_requestTask enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSURLSessionDataTask * _Nonnull obj, BOOL * _Nonnull stop) {
            [obj cancel];
        }];
        [_requestTask removeAllObjects];
    }];
}

- (void)cancelAllRequests
{
    [self runAsyc:^{
        [_requestTask enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSURLSessionDataTask * _Nonnull obj, BOOL * _Nonnull stop) {
            [obj cancel];
        }];
        [_requestTask removeAllObjects];
    }];
}

- (void)cancelRequestByKey:(NSString *)key
{
    [self runAsyc:^{
        NSURLSessionDataTask *task = [_requestTask objectForKey:key];
        if (task)
        {
            [task cancel];
            [_requestTask removeObjectForKey:key];
        }
    }];
}

- (NSString *)postRequestWithAPI:(NSString *)api
                         params:(NSDictionary *)params
                        success:(void (^)(id responseObject))success
                        failure:(void (^)(NSError *error))failure
{
    NSString *urlString = nil;
    if ([api hasPrefix:@"/"])
    {
        urlString = [NSString stringWithFormat:@"%@%@", TTSERVER_BASE_URL_STRING, api];
    }
    else
    {
        urlString = [NSString stringWithFormat:@"%@/%@", TTSERVER_BASE_URL_STRING, api];
    }
    
    return [self postRequestWithURLString:urlString params:params success:success failure:failure];
}

/*
 完整urlGet请求方法
 */
- (NSString *)postRequestWithURLString:(NSString *)urlString
                               params:(NSDictionary *)params
                              success:(void (^)(id responseObject))success
                              failure:(void (^)(NSError *error))failure
{
    NSString *key = [NSString stringWithFormat:@"%p => %@ %@", urlString, urlString, [[NSUUID UUID] UUIDString]];
    NSURLSessionDataTask *requestTask = nil;
    requestTask =
    [[TTURLSessionManager shareInstance] postRequestWithURLString:urlString params:params success:^(NSURLSessionDataTask *task, id responseObject) {
        NSAssert([NSThread isMainThread], @"当前不是主线程");
        [self runAsyc:^{
            [_requestTask removeObjectForKey:key];
        }];
        NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
        if (statusCode != 200)
        {
            if (failure)
            {
                NSError *myerror = [[NSError alloc] initWithDomain:TTNetHelperResponseDomain code:statusCode userInfo:@{TTNetHelperResponseUserDomainKey: @"服务异常"}];
                failure(myerror);
            }
        }
        else
        {
            if (success)
            {
                success(responseObject);
            }
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSAssert([NSThread isMainThread], @"当前不是主线程");
        [self runAsyc:^{
            [_requestTask removeObjectForKey:key];
        }];
        
        if (failure)
        {
            NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
            NSLog(@"statuc code = %ld error: %@", statusCode, error);
            NSError *myerror = [[NSError alloc] initWithDomain:TTNetHelperResponseDomain code:statusCode userInfo:@{TTNetHelperResponseUserDomainKey: @"网络异常"}];
            failure(myerror);
        }
    }];
    
    [self runAsyc:^{
        [_requestTask setObject:requestTask forKey:key];
    }];
    
    return key;
}

- (NSString *)getRequestWithAPI:(NSString *)api
                         params:(NSDictionary *)params
                        success:(void (^)(id responseObject))success
                        failure:(void (^)(NSError *error))failure
{
    NSString *urlString = nil;
    if ([api hasPrefix:@"/"])
    {
        urlString = [NSString stringWithFormat:@"%@%@", TTSERVER_BASE_URL_STRING, api];
    }
    else
    {
        urlString = [NSString stringWithFormat:@"%@/%@", TTSERVER_BASE_URL_STRING, api];
    }
    
    return [self getRequestWithURLString:urlString params:params success:success failure:failure];
}

/*
    完整urlGet请求方法
 */
- (NSString *)getRequestWithURLString:(NSString *)urlString
                               params:(NSDictionary *)params
                              success:(void (^)(id responseObject))success
                              failure:(void (^)(NSError *error))failure
{
    NSString *key = [NSString stringWithFormat:@"%p => %@ %@", urlString, urlString, [[NSUUID UUID] UUIDString]];
    NSURLSessionDataTask *requestTask = nil;
    requestTask =
    [[TTURLSessionManager shareInstance] getRequestWithURLString:urlString params:params success:^(NSURLSessionDataTask *task, id responseObject) {
        NSAssert([NSThread isMainThread], @"当前不是主线程");
        [self runAsyc:^{
            [_requestTask removeObjectForKey:key];
        }];
        NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
        if (statusCode != 200)
        {
            if (failure)
            {
                NSError *myerror = [[NSError alloc] initWithDomain:TTNetHelperResponseDomain code:statusCode userInfo:@{TTNetHelperResponseUserDomainKey: @"服务异常"}];
                failure(myerror);
            }
        }
        else
        {
            if (success)
            {
                success(responseObject);
            }
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSAssert([NSThread isMainThread], @"当前不是主线程");
        [self runAsyc:^{
            [_requestTask removeObjectForKey:key];
        }];

        if (failure)
        {
            NSInteger statusCode = ((NSHTTPURLResponse *)task.response).statusCode;
            NSLog(@"statuc code = %ld error: %@", statusCode, error);
            NSError *myerror = [[NSError alloc] initWithDomain:TTNetHelperResponseDomain code:statusCode userInfo:@{TTNetHelperResponseUserDomainKey: @"网络异常"}];
            failure(myerror);
        }
    }];
    
    [self runAsyc:^{
        [_requestTask setObject:requestTask forKey:key];
    }];
    
    return key;
}


- (void)runAsyc:(void(^)())block
{
    if (!block)
        return ;
    
    if (dispatch_get_specific(&_requestTask))
    {
        block();
    }
    else
    {
        dispatch_async(_requestTaskCacheQueue, block);
    }
}

- (void)runSyc:(void(^)())block
{
    if (!block)
        return ;
    
    if (dispatch_get_specific(&_requestTask))
    {
        block();
    }
    else
    {
        dispatch_sync(_requestTaskCacheQueue, block);
    }
}


@end
